package com.kgc.sbt.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.kgc.sbt.api.BuyLimitApi;
import com.kgc.sbt.api.GoodsApi;
import com.kgc.sbt.config.BuyLimitConfig;
import com.kgc.sbt.service.BuyLimitService;
import com.kgc.sbt.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * Created on 2021/6/23.
 * <p>
 * Author: GongMingJie
 * <p>
 * Description:
 */
@Service
public class BuyLimitServiceImpl implements BuyLimitService {

    @Autowired
    private BuyLimitConfig buyLimitConfig;

    @Autowired
    private RedisUtils redisUtils;

    @Reference
    private GoodsApi goodsApi;

    @Reference
    private BuyLimitApi buyLimitApi;

    @Override
    public boolean initGoodsStockToRedis(String goodsId) {
        // 从redis获取商品库存数量，如果已经存在，就不需要重复添加
        // 如果redis中没有，需要存入redis
        return redisUtils.get(buyLimitConfig.getStockNumPrefix() + goodsId) == null
                && redisUtils.set(buyLimitConfig.getStockNumPrefix() + goodsId, goodsApi.queryGoodsById(Integer.valueOf(goodsId)).getStock());
    }

    @Override
    public boolean lockBuyUser(String userId, String goodsId,Integer buyLimitId) {

        // 借助redis的分布式锁，锁定用户，要使用名称空间概念
        return redisUtils.lock(buyLimitConfig.getLockUserPrefix() + goodsId + ":" + userId, null, buyLimitApi.getBuyLimitTime(buyLimitId));
    }

    @Override
    public boolean checkProdStock(String goodsId, Integer buyCount) {
        // 从redis获取当前商品库存
        Object prodStockNum = redisUtils.get(buyLimitConfig.getStockNumPrefix() + goodsId);

        // 如果库存存在且充足，返回true，否则返回false
        return prodStockNum != null && Integer.valueOf(prodStockNum.toString()) >= buyCount;

    }

    @Override
    public boolean isStockLock(String goodsId) {
        // 直接进行上锁，（setnx，如果已经锁定，上锁失败），上锁成功，没有用抢购，可以进行后续流程，如果上锁失败，代表有人抢购，等待
        return !redisUtils.lock(buyLimitConfig.getStockLockPrefix() + goodsId, null, buyLimitConfig.getStockLockTime());
    }

    @Override
    public boolean isTradeOrderCreated(String tradeOrderNo) {
        return ObjectUtils.isEmpty(redisUtils.get(tradeOrderNo));
    }

    @Override
    public void subProdStockNum(String goodsId, Integer buyCount) {
        redisUtils.decr(buyLimitConfig.getStockNumPrefix() + goodsId, buyCount);
    }

    @Override
    public void unlockProdStockLock(String goodsId) {
        redisUtils.delLock(buyLimitConfig.getStockLockPrefix() + goodsId);
    }
}
